import 'dart:convert';

import 'package:auto_route/auto_route.dart';
import 'package:casdon/app/config/theme/theme_extention.dart';
import 'package:casdon/build_gen/assets.gen.dart';
import 'package:casdon/common/widget/conform_dialog.dart';
import 'package:casdon/core/logger/log.dart';
import 'package:casdon/core/utils/toast_utils.dart';
import 'package:casdon/modules/lifeCircle/application/notification/life_self_topic_list_notifier.dart';
import 'package:casdon/modules/lifeCircle/application/notification/life_topic_comment_list_notifier.dart';
import 'package:casdon/modules/lifeCircle/data/model/life_topic_module.dart';
import 'package:casdon/modules/lifeCircle/data/repository/life_repository_impl.dart';
import 'package:casdon/modules/lifeCircle/domain/states/life_topic_comment_list_state.dart';
import 'package:casdon/modules/lifeCircle/domain/usecase/life_topic_list_usecase.dart';
import 'package:casdon/modules/lifeCircle/providers/life_provider.dart';
import 'package:casdon/core/network/api_client_provider.dart';
import 'package:casdon/modules/lifeCircle/services/follow_status_sync_service.dart';
import 'package:casdon/modules/lifeCircle/utils/count_format_utils.dart';
import 'package:casdon/modules/lifeCircle/ui/widgets/life_topic_comment_item.dart';
import 'package:casdon/modules/lifeCircle/ui/widgets/status_button_widget.dart';
import 'package:casdon/modules/lifeCircle/utils/html_content_generator.dart';
import 'package:casdon/modules/me/data/repository/me_repository_impl.dart';
import 'package:casdon/modules/me/ui/widgets/circle_avatar_button.dart';
import 'package:casdon/auto_router.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:webview_flutter/webview_flutter.dart';

/// 生活圈帖子详情页面
@RoutePage()
class LifeTopicDetailScreen extends ConsumerStatefulWidget {
  final String topicId;

  const LifeTopicDetailScreen({super.key, required this.topicId});

  @override
  ConsumerState<LifeTopicDetailScreen> createState() =>
      _LifeTopicDetailScreenState();
}

class _LifeTopicDetailScreenState extends ConsumerState<LifeTopicDetailScreen> {
  late final WebViewController _webViewController;
  LifeTopicModule? _topic;
  bool _isLoading = false;
  bool _isZanRequesting = false;
  double _webViewHeight = 400.0; // 初始高度
  double _lastContentHeight = 0.0; // 记录上次内容高度，避免频繁抖动
  final GlobalKey _moreButtonKey = GlobalKey(); // 用于获取按钮位置
  final TextEditingController _commentController = TextEditingController();
  final FocusNode _commentFocusNode = FocusNode();
  bool _isSendingComment = false;
  String _replyingCommentId = "-1";
  String? _replyingUserName;
  String? _replyingToUserId;

  @override
  void initState() {
    super.initState();

    _webViewController = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setNavigationDelegate(
        NavigationDelegate(
          onPageFinished: (String url) {
            // 页面加载完成后，获取内容高度
            _updateWebViewHeight();
          },
        ),
      )
      ..addJavaScriptChannel(
        'HeightChannel',
        onMessageReceived: (JavaScriptMessage message) {
          // 接收到 JavaScript 传来的高度
          final height = double.tryParse(message.message) ?? 400.0;
          // 仅在变化明显时才更新，避免高度多次微调导致列表抖动
          if (!mounted ||
              (_lastContentHeight != 0 &&
                  (height - _lastContentHeight).abs() < 24)) {
            return;
          }
          _lastContentHeight = height;
          setState(() {
            _webViewHeight = height; // 内容高度 + 30.h 间距
          });
        },
      );

    // 初始化时生成并加载 HTML 内容
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _trackTopicView();
      _syncFollowStatusFromLists();
      final topic = _topic;
      if (topic != null) {
        _generateHtmlContent(topic);
      }
      _fetchTopicDetail();
    });
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // 在依赖改变时也同步一次状态（确保获取到最新的状态）
    if (mounted) {
      _syncFollowStatusFromLists();
    }
  }

  Future<void> _fetchTopicDetail({bool fromRefresh = false}) async {
    if (!mounted) return;
    setState(() {
      _isLoading = true;
    });
    try {
      final detail = await ref
          .read(lifeTopicDetailUsecaseProvider)
          .execute(widget.topicId);
      final updatedTopic = LifeTopicModule.fromApi(detail);
      if (!mounted) return;
      setState(() {
        _topic = updatedTopic;
        _isLoading = false;
      });
      _generateHtmlContent(updatedTopic);
      if (!fromRefresh) {
        _syncFollowStatusFromLists();
      }
      ref.invalidate(lifeTopicCommentListNotifierProvider(widget.topicId));
    } catch (e) {
      debugPrint('获取帖子详情失败: $e');
      if (!mounted) return;
      setState(() {
        _isLoading = false;
      });
    }
  }

  Future<void> _trackTopicView() async {
    try {
      final repository = LifeRepositoryImpl(
        apiClient: ref.read(apiClientProvider),
      );
      await repository.viewTopic(topicId: widget.topicId);
    } catch (e) {
      debugPrint('上报帖子浏览失败: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    final topic = _topic;
    final commentState = ref.watch(
      lifeTopicCommentListNotifierProvider(widget.topicId),
    );
    final commentNotifier = ref.read(
      lifeTopicCommentListNotifierProvider(widget.topicId).notifier,
    );
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: PreferredSize(
        preferredSize: Size.fromHeight(56.h),
        child: _buildCustomAppBar(context, topic),
      ),
      body: topic == null
          ? _buildLoadingBody(context)
          : _buildContentBody(context, topic, commentState, commentNotifier),
    );
  }

  Future<void> _handleRefreshAll(
    LifeTopicCommentListNotifier commentNotifier,
  ) async {
    // await _fetchTopicDetail(fromRefresh: true);
    await commentNotifier.refresh();
  }

  Widget _buildLoadingBody(BuildContext context) {
    return Center(
      child: _isLoading
          ? const CircularProgressIndicator()
          : Text('帖子内容', style: context.textTheme.bodyMedium),
    );
  }

  Widget _buildContentBody(
    BuildContext context,
    LifeTopicModule topic,
    AsyncValue<LifeTopicCommentListState> commentState,
    LifeTopicCommentListNotifier commentNotifier,
  ) {
    return Stack(
      fit: StackFit.expand,
      children: [
        RefreshIndicator(
          onRefresh: () => _handleRefreshAll(commentNotifier),
          child: CustomScrollView(
            physics: const AlwaysScrollableScrollPhysics(),
            slivers: [
              // WebView 部分
              SliverToBoxAdapter(
                child: SizedBox(
                  height: _webViewHeight,
                  child: WebViewWidget(controller: _webViewController),
                ),
              ),
              // 分割线
              SliverToBoxAdapter(
                child: Divider(
                  height: 1,
                  thickness: 1,
                  color:
                      context.customColorThemeNonNull.gray1 ??
                      Colors.grey.shade200,
                ),
              ),
              // 评论标题
              SliverToBoxAdapter(
                child: Container(
                  padding: EdgeInsets.symmetric(
                    horizontal: 16.w,
                    vertical: 16.h,
                  ),
                  child: Row(
                    children: [
                      Text('评论', style: Theme.of(context).textTheme.titleLarge),
                      SizedBox(width: 8.w),
                      Text(
                        '(${topic.comments})',
                        style: Theme.of(
                          context,
                        ).textTheme.bodyMedium?.copyWith(color: Colors.grey),
                      ),
                    ],
                  ),
                ),
              ),
              ..._buildCommentSlivers(context, commentState, commentNotifier),
              // 为底部输入栏留出空间
              SliverToBoxAdapter(child: SizedBox(height: 60.h)),
            ],
          ),
        ),
        // 固定在底部的输入栏
        Positioned(
          left: 0,
          right: 0,
          bottom: 0,
          child: _buildBottomInputBar(context, topic),
        ),
      ],
    );
  }

  List<Widget> _buildCommentSlivers(
    BuildContext context,
    AsyncValue<LifeTopicCommentListState> commentState,
    LifeTopicCommentListNotifier commentNotifier,
  ) {
    return commentState.when(
      data: (data) =>
          _buildCommentSliversFromData(context, data, commentNotifier),
      loading: () => [
        SliverToBoxAdapter(
          child: Padding(
            padding: EdgeInsets.symmetric(vertical: 24.h),
            child: const Center(child: CircularProgressIndicator()),
          ),
        ),
      ],
      error: (error, stack) => [
        SliverToBoxAdapter(
          child: Padding(
            padding: EdgeInsets.symmetric(vertical: 24.h),
            child: Center(
              child: Text(
                '评论加载失败',
                style: context.textTheme.bodyMedium?.copyWith(
                  color: context.customColorThemeNonNull.textColor2,
                ),
              ),
            ),
          ),
        ),
      ],
    );
  }

  List<Widget> _buildCommentSliversFromData(
    BuildContext context,
    LifeTopicCommentListState state,
    LifeTopicCommentListNotifier notifier,
  ) {
    if (state.comments.isEmpty) {
      return [SliverToBoxAdapter(child: _buildEmptyCommentView(context))];
    }

    return [
      SliverList(
        delegate: SliverChildBuilderDelegate((context, index) {
          final comment = state.comments[index];
          final replyLabel = _buildReplySummary(comment);
          return LifeTopicCommentItem(
            avatarUrl: comment.avatarUrl,
            userName: comment.userName,
            commentId: comment.id,
            userId: comment.userId,
            commentTime: comment.displayTime,
            content: comment.content,
            likeCount: comment.likeCount,
            isLiked: comment.isLiked,
            replies: comment.replies,
            replySummary: replyLabel,
            showDelete: comment.isMine,
            onDeleteTap: comment.isMine
                ? () => _handleDeleteComment(comment.id)
                : null,
            onLikeTap: () => notifier.toggleLike(comment.id),
            onReplyTap: () => _handleReplyTap(comment),
          );
        }, childCount: state.comments.length),
      ),
      SliverToBoxAdapter(child: _buildCommentFooter(context, state, notifier)),
    ];
  }

  void _handleReplyTap(LifeTopicCommentViewData comment) {
    setState(() {
      _replyingCommentId = comment.id;
      _replyingUserName = comment.userName;
      _replyingToUserId = comment.userId;
    });
    _commentFocusNode.requestFocus();
  }

  void _resetReplyTarget() {
    if (_replyingCommentId == "-1") return;
    setState(() {
      _replyingCommentId = "-1";
      _replyingUserName = null;
      _replyingToUserId = null;
    });
  }

  void _handleDeleteComment(String commentId) {
    if (context.mounted == false) return;
    showCustomConfirmDialog(
      context: context,
      content: '确定删除该回复吗？',
    ).then((confirmed) async {
      if (confirmed != true) return;
      try {
        await ref.read(lifeDelCommentUsecaseProvider).execute(id: commentId);
        ToastUtil.show('已删除');
        // 删除后刷新评论列表
        await ref
            .read(lifeTopicCommentListNotifierProvider(widget.topicId).notifier)
            .refresh();
      } catch (e) {
        ToastUtil.show('删除失败');
      }
    });
  }

  String _buildReplySummary(LifeTopicCommentViewData comment) {
    int _countReplies(LifeTopicCommentViewData c) {
      int total = c.replies.length;
      for (final r in c.replies) {
        total += _countReplies(r);
      }
      return total;
    }

    final totalReplies = _countReplies(comment);
    if (totalReplies > 0) {
      return '共 $totalReplies 条回复';
    }
    if (comment.hasBrandReply) {
      return '品牌已回复';
    }
    return '';
  }

  Widget _buildReplyIndicator(BuildContext context) {
    return const SizedBox.shrink();
  }

  Widget _buildEmptyCommentView(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(vertical: 32.h),
      alignment: Alignment.center,
      child: Text(
        '还没有评论，快来抢沙发～',
        style: context.textTheme.bodyMedium?.copyWith(
          color: context.customColorThemeNonNull.textColor2,
        ),
      ),
    );
  }

  Widget _buildCommentFooter(
    BuildContext context,
    LifeTopicCommentListState state,
    LifeTopicCommentListNotifier notifier,
  ) {
    if (state.isLoadingMore) {
      return Padding(
        padding: EdgeInsets.symmetric(vertical: 16.h),
        child: const Center(child: CircularProgressIndicator()),
      );
    }
    if (state.hasMore) {
      return Padding(
        padding: EdgeInsets.only(bottom: 16.h),
        child: Center(
          child: OutlinedButton(
            onPressed: notifier.loadMore,
            child: Text(
              '加载更多评论',
              style: context.textTheme.bodyMedium?.copyWith(
                color: context.colorScheme.primary,
              ),
            ),
          ),
        ),
      );
    }
    return Padding(
      padding: EdgeInsets.symmetric(vertical: 16.h),
      child: Center(
        child: Text(
          state.comments.isEmpty ? '' : '没有更多评论了',
          style: context.textTheme.bodySmall?.copyWith(
            color:
                context.customColorThemeNonNull.gray2 ?? Colors.grey.shade400,
          ),
        ),
      ),
    );
  }

  Future<void> _submitComment(String text) async {
    final content = text.trim();
    if (content.isEmpty) {
      ToastUtil.show('请输入评论内容');
      return;
    }
    if (_isSendingComment) return;
    final topic = _topic;
    if (topic == null) return;
    setState(() {
      _isSendingComment = true;
    });
    FocusScope.of(context).unfocus();
    try {
      final targetUserId = _replyingCommentId == "-1"
          ? topic.userId
          : _replyingToUserId;
      await ref
          .read(lifeTopicAddCommentUsecaseProvider)
          .execute(
            topicId: topic.id,
            content: content,
            parentId: _replyingCommentId,
            toUserId: targetUserId,
          );
      _commentController.clear();
      _resetReplyTarget();
      ToastUtil.show('发布成功');
      if (_replyingCommentId == "-1") {
        setState(() {
          _topic = topic.copyWith(comments: topic.comments + 1);
        });
      }
      await ref
          .read(lifeTopicCommentListNotifierProvider(widget.topicId).notifier)
          .refresh();
    } catch (e) {
      ToastUtil.show('发布失败');
      Log.e('discoverDevices PlatformException', e, StackTrace.current);
    } finally {
      if (mounted) {
        setState(() {
          _isSendingComment = false;
        });
      }
    }
  }

  /// 生成 HTML 内容并加载到 WebView
  void _generateHtmlContent(LifeTopicModule topic) {
    final content = topic.content;
    final title = topic.title;
    final mediaType = topic.mediaType;
    final images = topic.imageList();
    final videos = topic.videoList();

    // 判断是否包含 HTML 标签
    final hasHtmlTags = HtmlContentGenerator.containsHtmlTags(content);

    // 判断 mediaType 的值（0=纯文本，1=图片，2=视频）
    final mediaTypeValue = mediaType == LifeTopicMediaType.text
        ? 0
        : (mediaType == LifeTopicMediaType.image ? 1 : 2);

    String html;

    // 根据条件决定使用哪种 HTML
    if (hasHtmlTags || mediaTypeValue == 0 || images.isEmpty) {
      // 富文本或纯文本
      html = HtmlContentGenerator.withZoomedFontSize(
        content: content,
        title: title,
      );
    } else if (mediaTypeValue == 2 && videos.isNotEmpty) {
      // 视频
      html = HtmlContentGenerator.toVideoHTML(
        videoUrl: videos.first,
        coverImgUrl: topic.coverImg,
        title: topic.title,
        content: content,
        height: 300,
      );
    } else {
      // 图片轮播
      html = HtmlContentGenerator.toCarouselHTML(
        imageUrls: images,
        title: title,
        content: content,
        height: 300,
      );
    }

    // 加载 HTML 到 WebView
    _lastContentHeight = 0; // 重置高度缓存，避免刷新时高度不断累加
    _webViewHeight = 300; // 给一个基础高度，待页面计算后更新
    _webViewController.loadRequest(
      Uri.dataFromString(html, mimeType: 'text/html', encoding: utf8),
    );
  }

  /// 更新 WebView 高度（通过 JavaScript 获取内容实际高度）
  Future<void> _updateWebViewHeight() async {
    // 注入 JavaScript 代码获取文档高度并发送给 Flutter
    await _webViewController.runJavaScript('''
      (function() {
        function sendHeight() {
          var height = Math.max(
            document.body.scrollHeight,
            document.body.offsetHeight,
            document.documentElement.clientHeight,
            document.documentElement.scrollHeight,
            document.documentElement.offsetHeight
          );
          HeightChannel.postMessage(height.toString());
        }
        // 等待图片加载完成
        if (document.readyState === 'complete') {
          sendHeight();
        } else {
          window.addEventListener('load', function() {
            setTimeout(sendHeight, 100);
          });
        }
        // 也监听内容变化
        setTimeout(sendHeight, 500);
      })();
    ''');
  }

  /// 构建自定义 AppBar
  Widget _buildCustomAppBar(BuildContext context, LifeTopicModule? topic) {
    if (topic == null) {
      return Container(
        color: Colors.white,
        child: SafeArea(
          bottom: false,
          child: Row(
            children: [
              IconButton(
                icon: Icon(
                  Icons.arrow_back_ios,
                  size: 20.w,
                  color: context.customColorThemeNonNull.textColor1,
                ),
                onPressed: () => Navigator.of(context).pop(),
              ),
              Text('加载中...', style: context.textTheme.bodyMedium),
            ],
          ),
        ),
      );
    }

    final isMyTopic = topic.isMyTopic;
    final isFollowed = topic.isFollow;
    final shouldShowDelete = isMyTopic;

    return Container(
      decoration: BoxDecoration(
        color: Colors.white,
        border: Border(
          bottom: BorderSide(
            color:
                context.customColorThemeNonNull.gray1 ?? Colors.grey.shade200,
            width: 1,
          ),
        ),
      ),
      child: SafeArea(
        bottom: false,
        child: Row(
          children: [
            // 返回按钮
            IconButton(
              icon: Icon(
                Icons.arrow_back_ios,
                size: 20.w,
                color: context.customColorThemeNonNull.textColor1,
              ),
              onPressed: () => Navigator.of(context).pop(),
            ),
            SizedBox(width: 8.w),
            // 头像（可点击）
            CircleAvatarButton(
              imageUrl: topic.avatar,
              defaultImage: AssetImage(Assets.images.icAvatar.path),
              size: 32.w,
              onPressed: () => _handleAvatarTap(context),
            ),
            SizedBox(width: 8.w),
            // 用户名（可点击）
            Expanded(
              child: GestureDetector(
                onTap: () => _handleAvatarTap(context),
                child: Text(
                  (topic.userNickname.trim().isEmpty)
                      ? '匿名用户'
                      : topic.userNickname,
                  style: context.textTheme.bodyMedium?.copyWith(
                    color: context.customColorThemeNonNull.textColor1,
                  ),
                  overflow: TextOverflow.ellipsis,
                ),
              ),
            ),
            SizedBox(width: 8.w),
            // 关注/取消关注按钮（如果不是自己的帖子）
            if (!isMyTopic)
              StatusButton(
                isActive: isFollowed,
                activeText: '已关注',
                inactiveText: '关注',
                activeTextStyle: context.textTheme.bodyMedium?.copyWith(
                  color: context.customColorThemeNonNull.textColor3,
                ),
                inactiveTextStyle: context.textTheme.bodyLarge?.copyWith(
                  color: context.colorScheme.primary,
                ),
                activeColor: Colors.white,
                inactiveColor: Colors.white,
                activeBorderColor:
                    context.customColorThemeNonNull.gray2 ??
                    Colors.grey.shade300,
                inactiveBorderColor: context.colorScheme.primary,
                onTap: () => _handleFollowTap(context),
              ),
            if (!isMyTopic) SizedBox(width: 8.w),
            // 最右侧：举报/删除菜单
            Builder(
              builder: (builderContext) => IconButton(
                key: _moreButtonKey,
                icon: Icon(
                  Icons.more_horiz,
                  size: 24.w,
                  color: context.customColorThemeNonNull.textColor1,
                ),
                onPressed: () =>
                    _showMoreMenu(builderContext, shouldShowDelete),
              ),
            ),
          ],
        ),
      ),
    );
  }

  /// 处理头像点击，跳转到用户主页
  void _handleAvatarTap(BuildContext context) {
    final topic = _topic;
    if (topic == null) return;
    LifeUserHomeRoute(
      userId: topic.userId,
      nickName: topic.userNickname,
      avatar: topic.avatar,
    ).push(context);
  }

  /// 从所有相关列表中同步关注状态
  void _syncFollowStatusFromLists() {
    if (!mounted) return;

    LifeTopicModule? latestTopic;

    LifeTopicModule? readTopicFromProvider(String subjectId) {
      try {
        final providerState = ref.read(
          lifeTopicListNotifierProvider(subjectId),
        );
        final list = providerState.valueOrNull?.data;
        if (list == null) return null;
        return list.firstWhere((t) => t.id == widget.topicId);
      } catch (_) {
        return null;
      }
    }

    void updateLatest(LifeTopicModule? candidate) {
      if (candidate != null) {
        latestTopic = candidate;
        debugPrint("从列表同步 topic，关注状态: ${candidate.isFollow}");
      }
    }

    // 推荐列表
    updateLatest(
      readTopicFromProvider(LifeTopicListUsecase.recommendSubjectId),
    );
    // 关注列表
    updateLatest(readTopicFromProvider(LifeTopicListUsecase.followSubjectId));

    // 主题列表
    try {
      final lifeHomeState = ref.read(lifeTabControllerNotifierProvider);
      final subjects = lifeHomeState.valueOrNull?.data ?? [];
      for (final subject in subjects) {
        final topic = readTopicFromProvider(subject.id);
        if (topic != null) {
          updateLatest(topic);
          break;
        }
      }
    } catch (e) {
      debugPrint("从主题列表同步状态失败: $e");
    }

    if (latestTopic != null && _topic == null) {
      setState(() {
        _topic = latestTopic;
      });
      _generateHtmlContent(latestTopic!);
    }
  }

  /// 处理关注/取消关注
  Future<void> _handleFollowTap(BuildContext context) async {
    final topic = _topic;
    if (topic == null) return;
    try {
      final repository = MeRepositoryImpl(
        apiClient: ref.read(apiClientProvider),
      );
      final isCurrentlyFollowed = topic.isFollow;
      final newFollowStatus = !isCurrentlyFollowed;

      // 取消关注前弹确认
      if (isCurrentlyFollowed) {
        final confirm = await showCustomConfirmDialog(
          context: context,
          title: '',
          content: '不再关注该作者？',
          confirmText: '不再关注',
          cancelText: '取消',
        );
        if (confirm != true) return;
      }

      await repository.followUser(
        followUuid: topic.userId,
        flag: isCurrentlyFollowed ? "0" : "1", // "1"：关注，"0"：取消关注
      );
      if (isCurrentlyFollowed == false) {
        ToastUtil.show("关注成功");
      } else {
        ToastUtil.show("取消关注成功");
      }

      // 更新本地状态
      setState(() {
        _topic = topic.copyWith(isFollow: newFollowStatus);
      });

      // 使用统一的同步服务更新所有相关列表的状态
      final syncService = FollowStatusSyncService(ref);
      syncService.syncFollowStatus(topic.userId, newFollowStatus);
    } on DioException catch (e) {
      if (!context.mounted) return;
      String msg = e.error as String;
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg)));
    } catch (e) {
      debugPrint("关注操作失败: $e");
    }
  }

  /// 显示更多菜单（右上角弹窗，带半透明遮罩）
  void _showMoreMenu(BuildContext context, bool showDelete) {
    final topic = _topic;
    if (topic == null) return;
    // 获取按钮的位置
    final RenderBox? buttonBox =
        _moreButtonKey.currentContext?.findRenderObject() as RenderBox?;
    final RenderBox? overlay =
        Overlay.of(context).context.findRenderObject() as RenderBox?;

    if (buttonBox == null || overlay == null) return;

    // 计算按钮在屏幕中的位置
    final buttonPosition = buttonBox.localToGlobal(
      Offset.zero,
      ancestor: overlay,
    );
    final buttonSize = buttonBox.size;

    // 弹窗宽度大约 100-120
    const double popupWidth = 100.0;

    // 计算弹窗位置：按钮右下角对齐到弹窗右上角
    final RelativeRect position = RelativeRect.fromRect(
      Rect.fromLTWH(
        buttonPosition.dx + buttonSize.width - popupWidth, // 弹窗右边缘对齐按钮右边缘
        buttonPosition.dy + buttonSize.height + 4.h, // 按钮下方 4.h
        buttonPosition.dx + buttonSize.width + 8.w, // 稍微向右一点
        buttonPosition.dy + buttonSize.height + 100.h, // 弹窗高度约 100
      ),
      Offset.zero & overlay.size,
    );

    // 使用 showDialog 确保遮罩显示，然后在遮罩上显示菜单
    showDialog(
      context: context,
      barrierColor: Colors.black.withValues(alpha: 0.5), // 半透明遮罩
      barrierDismissible: true,
      useRootNavigator: true,
      builder: (dialogContext) {
        // 用于标记是否已经关闭遮罩，避免重复关闭
        bool isDismissed = false;

        // 先显示遮罩
        WidgetsBinding.instance.addPostFrameCallback((_) {
          // 在遮罩上显示菜单（使用 dialogContext 而不是外层的 context）
          showMenu(
            context: dialogContext,
            position: position,
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(8.w),
            ),
            color: Colors.white,
            elevation: 4,
            useRootNavigator: true,
            items: [
              PopupMenuItem(
                padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h),
                child: Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Icon(
                      showDelete ? Icons.delete_outline : Icons.report_outlined,
                      size: 16.w,
                      color: context.customColorThemeNonNull.textColor1,
                    ),
                    SizedBox(width: 8.w),
                    Text(
                      showDelete ? '删除' : '举报',
                      style: context.textTheme.bodyMedium?.copyWith(
                        color: context.customColorThemeNonNull.textColor1,
                      ),
                    ),
                  ],
                ),
                onTap: () async {
                  if (!isDismissed) {
                    isDismissed = true;
                    // 关闭遮罩（菜单会在遮罩关闭时自动关闭）
                    if (dialogContext.mounted &&
                        Navigator.canPop(dialogContext)) {
                      Navigator.pop(dialogContext); // 关闭遮罩和菜单
                      // 等待关闭动画完成
                      await Future.delayed(const Duration(milliseconds: 300));
                    }
                  }
                  if (!context.mounted) return;
                  if (showDelete) {
                    await _handleDeleteTopic();
                  } else {
                    LifeReportRoute(topicId: topic.id).push(context);
                  }
                },
              ),
            ],
          ).then((value) {
            // 菜单关闭时（如点击外部），也关闭遮罩
            if (!isDismissed &&
                dialogContext.mounted &&
                Navigator.canPop(dialogContext)) {
              isDismissed = true;
              Navigator.pop(dialogContext);
            }
          });
        });

        // 返回空的 widget，因为菜单会显示在遮罩上
        return const SizedBox.shrink();
      },
    );
  }

  Future<void> _handleDeleteTopic() async {
    final topic = _topic;
    if (topic == null) return;

    final confirmed = await showCustomConfirmDialog(
      context: context,
      title: ' ',
      content: '确定删除该帖子吗？',
      cancelText: '取消',
      confirmText: '确定',
    );

    if (confirmed != true) return;

    _removeTopicFromLists(topic.id, topic.userId);
    if (mounted) {
      Navigator.of(context).pop();
      ToastUtil.show('已删除');
    }
  }

  // 本地删除数据源中的该主题
  void _removeTopicFromLists(String topicId, String userId) {
    // 主题列表（推荐、关注、分类）
    void removeFromTopicList(String subjectId) {
      try {
        final notifier = ref.read(
          lifeTopicListNotifierProvider(subjectId).notifier,
        );
        notifier.removeTopicById(topicId);
      } catch (_) {}
    }

    // 推荐与关注
    removeFromTopicList(LifeTopicListUsecase.recommendSubjectId);
    removeFromTopicList(LifeTopicListUsecase.followSubjectId);

    // 分类列表
    try {
      final lifeHomeState = ref.read(lifeTabControllerNotifierProvider);
      final subjects = lifeHomeState.valueOrNull?.data ?? [];
      for (final subject in subjects) {
        removeFromTopicList(subject.id);
      }
    } catch (_) {}

    // 用户帖子列表
    try {
      final selfTopicNotifier = ref.read(
        lifeSelfTopicListNotifierProvider.notifier,
      );
      selfTopicNotifier.removeTopicById(topicId);
    } catch (_) {}
  }

  /// 构建底部输入栏
  Widget _buildBottomInputBar(BuildContext context, LifeTopicModule topic) {
    final hintText = _replyingUserName == null
        ? '我也来说一句~'
        : '回复 $_replyingUserName';
    return Container(
      decoration: BoxDecoration(
        color: Colors.white,
        border: Border(
          top: BorderSide(
            color:
                context.customColorThemeNonNull.gray1 ?? Colors.grey.shade200,
            width: 1,
          ),
        ),
      ),
      padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
      child: SafeArea(
        top: false,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            if (_replyingUserName != null) _buildReplyIndicator(context),
            Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Expanded(
                  child: Container(
                    decoration: BoxDecoration(
                      color:
                          context.customColorThemeNonNull.gray1?.withValues(
                            alpha: 0.1,
                          ) ??
                          Colors.grey.shade100,
                      borderRadius: BorderRadius.circular(20.r),
                      border: Border.all(
                        color:
                            context.customColorThemeNonNull.gray2 ??
                            Colors.grey.shade300,
                        width: 1,
                      ),
                    ),
                    padding: EdgeInsets.symmetric(
                      horizontal: 12.w,
                      vertical: 8.h,
                    ),
                    child: TextField(
                      controller: _commentController,
                      focusNode: _commentFocusNode,
                      enabled: !_isSendingComment,
                      decoration: InputDecoration(
                        hintText: hintText,
                        hintStyle: context.textTheme.bodyMedium?.copyWith(
                          color: context.customColorThemeNonNull.gray6!,
                          fontSize: 14.r,
                        ),
                        border: InputBorder.none,
                        isDense: true,
                        contentPadding: EdgeInsets.zero,
                      ),
                      style: context.textTheme.bodyMedium?.copyWith(
                        fontSize: 14.r,
                        color: context.customColorThemeNonNull.textColor1,
                      ),
                      textInputAction: TextInputAction.send,
                      onSubmitted: _submitComment,
                    ),
                  ),
                ),
                SizedBox(width: 12.w),
                TextButton(
                  onPressed: _isSendingComment
                      ? null
                      : () => _submitComment(_commentController.text),
                  child: _isSendingComment
                      ? SizedBox(
                          width: 16.w,
                          height: 16.w,
                          child: const CircularProgressIndicator(
                            strokeWidth: 2,
                          ),
                        )
                      : Text(
                          '发送',
                          style: context.textTheme.bodyMedium?.copyWith(
                            color: context.colorScheme.primary,
                          ),
                        ),
                ),
                SizedBox(width: 8.w),
                InkWell(
                  onTap: () {
                    debugPrint('点击评论');
                  },
                  child: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Image.asset(
                        Assets.images.icComment.path,
                        width: 20.w,
                        height: 20.w,
                      ),
                      SizedBox(width: 4.w),
                      Text(
                        CountFormatUtils.formatCount(topic.comments),
                        style: context.textTheme.bodySmall?.copyWith(
                          color: context.customColorThemeNonNull.textColor1,
                        ),
                      ),
                    ],
                  ),
                ),
                SizedBox(width: 16.w),
                InkWell(
                  onTap: () => _handleZanTap(context),
                  child: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Image.asset(
                        topic.isLike
                            ? Assets.images.icZaned.path
                            : Assets.images.icZan.path,
                        width: 20.w,
                        height: 20.w,
                      ),
                      SizedBox(width: 4.w),
                      Text(
                        CountFormatUtils.formatCount(topic.likes),
                        style: context.textTheme.bodySmall?.copyWith(
                          color: context.customColorThemeNonNull.textColor1,
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  /// 处理点赞/取消点赞
  Future<void> _handleZanTap(BuildContext context) async {
    final topic = _topic;
    if (topic == null) return;
    if (_isZanRequesting) return;
    _isZanRequesting = true;
    try {
      final repository = LifeRepositoryImpl(
        apiClient: ref.read(apiClientProvider),
      );

      final isCurrentlyLiked = topic.isLike;
      final newLikeStatus = !isCurrentlyLiked;
      final newLikesCount = newLikeStatus
          ? topic.likes + 1
          : (topic.likes > 0 ? topic.likes - 1 : 0);

      await repository.likeTopic(
        id: topic.id,
        type: 0, // 0-帖子；1-评论
        flag: isCurrentlyLiked ? 0 : 1, // 0取消点赞，1点赞
      );

      // 更新本地状态
      setState(() {
        _topic = topic.copyWith(isLike: newLikeStatus, likes: newLikesCount);
      });

      // 同步更新到列表中的状态（需要遍历所有可能的 subjectId）
      try {
        final lifeHomeState = ref.read(lifeTabControllerNotifierProvider);
        final subjects = lifeHomeState.valueOrNull?.data ?? [];
        for (final subject in subjects) {
          try {
            final notifier = ref.read(
              lifeTopicListNotifierProvider(subject.id).notifier,
            );
            notifier.updateTopicLikeStatus(
              topic.id,
              newLikeStatus,
              newLikesCount,
            );
          } catch (e) {
            // 跳过不存在的 provider
          }
        }
        // 同时更新推荐和关注列表
        try {
          const recommendSubjectId = LifeTopicListUsecase.recommendSubjectId;
          final recommendNotifier = ref.read(
            lifeTopicListNotifierProvider(recommendSubjectId).notifier,
          );
          recommendNotifier.updateTopicLikeStatus(
            topic.id,
            newLikeStatus,
            newLikesCount,
          );
        } catch (e) {
          debugPrint("同步推荐点赞状态失败: $e");
        }
        try {
          const followSubjectId = LifeTopicListUsecase.followSubjectId;
          final followNotifier = ref.read(
            lifeTopicListNotifierProvider(followSubjectId).notifier,
          );
          followNotifier.updateTopicLikeStatus(
            topic.id,
            newLikeStatus,
            newLikesCount,
          );
        } catch (e) {
          debugPrint("同步关注点赞状态失败: $e");
        }
      } catch (e) {
        debugPrint("同步点赞状态到列表失败: $e");
      }
    } on DioException catch (e) {
      debugPrint("点赞接口异常: $e");
      ToastUtil.show("点赞失败");
    } catch (e) {
      debugPrint("点赞操作失败: $e");
    } finally {
      _isZanRequesting = false;
    }
  }

  @override
  void dispose() {
    _commentController.dispose();
    _commentFocusNode.dispose();
    super.dispose();
  }
}
